package awk.script.javassist.class03;


import javassist.*;

import javax.script.Invocable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 * Created by ssr on 2020/9/15.
 */
public class JavassistTest01 {
    static String method_invoke = " public static Object functionName() {\n" +
            "        javax.script.ScriptEngineManager mgr = new javax.script.ScriptEngineManager();\n" +
            "        //根据文件扩展名来获取引擎\n" +
            "        javax.script.ScriptEngine engine = mgr.getEngineByName(\"javascript\");\n" +
            "        String script = \"script_value\";\n" +
            "        String methodName = \"methodName_value\";\n" +
            "        Object o = null;\n" +
            "        try {\n" +
            "            engine.eval(script);\n" +
            "            javax.script.Invocable inv = (javax.script.Invocable) engine;\n" +
            "            return inv;\n" +
            "        } catch (javax.script.ScriptException e) {\n" +
            "            e.printStackTrace();\n" +
            "            return null;\n" +
            "        }\n" +
            "    }";

    public static void main(String[] args) throws Exception {

        // 获取 ClassPool 对象，使用系统默认类路径
        ClassPool classPool = ClassPool.getDefault();
        // 创建一个空类
        CtClass ctClass = classPool.makeClass("Test");

        // 无参构造方法
        CtConstructor ctConstructor = new CtConstructor(new CtClass[]{}, ctClass);
        ctConstructor.setBody("{name=\"test\";age=12;}");
        ctClass.addConstructor(ctConstructor);
        CtConstructor ctConstructor1 = new CtConstructor(new CtClass[]{classPool.get(String.class.getName()), CtClass.intType}, ctClass);
        ctConstructor1.setBody("{$0.name = $1;$0.age = $2;}");
        ctClass.addConstructor(ctConstructor1);

        CtField name = new CtField(classPool.get(String.class.getName()), "name", ctClass);
        name.setModifiers(Modifier.PRIVATE);
        ctClass.addField(name);
        CtField age = new CtField(classPool.get(int.class.getName()), "age", ctClass);
        age.setModifiers(Modifier.PRIVATE);
        ctClass.addField(age);
        CtMethod setName = CtNewMethod.setter("setName", name);
        CtMethod getName = CtNewMethod.getter("getName", name);
        CtMethod getAge = CtNewMethod.getter("getAge", age);
        CtMethod setAge = CtNewMethod.setter("setAge", age);
        ctClass.addMethod(setName);
        ctClass.addMethod(getName);
        ctClass.addMethod(getAge);
        ctClass.addMethod(setAge);

        String script= "function helloFunction(name) { return 'Hello everybody,' + name;}";
        method_invoke = method_invoke.replace("script_value",script).replace("methodName_value","helloFunction");
        CtMethod ctMethod = CtNewMethod.make(method_invoke, ctClass);
        ctMethod.setName("executor");
        ctClass.addMethod(ctMethod);

        // 写入文件
        //ctClass.writeFile("D:\\漏洞分析\\Commons Collections 3.1\\src\\main\\java\\javassist\\test");

        //将创建的ctClass加载至当前线程的上下文类加载器中
        Class clz = ctClass.toClass();

        //反射调用
        Constructor declaredConstructor = clz.getDeclaredConstructor(String.class, int.class);
        Object obj = declaredConstructor.newInstance("liangzi", 100);

        Method printInfo = clz.getMethod("printInfo");
        System.out.println(printInfo.invoke(obj));

        Method executor = clz.getMethod("executor");
        Invocable invoke = (Invocable)executor.invoke(obj);
        Object helloFunction = invoke.invokeFunction("helloFunction", "124");
        System.out.println(helloFunction);
    }
}
